package org.NooLab.glue.components;

import java.util.Observable;
import java.util.Observer;

import org.NooLab.glue.MessageBoard;
import org.NooLab.glue.components.pkg.TaskPackage;
import org.NooLab.glue.instances.ParticipantsDeliveryPadIntf;
import org.NooLab.glue.interfaces.ReceptorDigestIntf;
import org.NooLab.glue.msgframe.XMessage;
import org.NooLab.glue.msgframe.XRegistration;
import org.NooLab.glue.net.ComBoxIntf;
import org.NooLab.glue.net.sockets.udp.UdpDataReceiver;
import org.NooLab.glue.transaction.Transaction;
import org.NooLab.utilities.files.DFutils;
import org.NooLab.utilities.logging.PrintLog;
import org.NooLab.utilities.strings.StringsUtil;
import org.NooLab.utilities.objects.StringedObjects;



/**
 * 
 *  
 *  this is for the low-level communication with/via the MessageBoard;
 *      its purpose is to represent a "RECEPTOR", i.e. it is accepting data sent by a
 *  "SOURCE" to the MessageBoard, performing some changes/calculations, then preparing
 *  the message and sending it back to the MessageBoard;
 *  
 *  The RECEPTOR is totally agnostic about the type or identity of the SOURCE   
 * 
 *      it needs to implement a particular interface, which mainly cares about referencing
 *  to the appropriate classes/objects needed to prepare the messages properly
 *  
 *  the counterpart for SOURCEs is given by the class "DataConnector{}"
 *  (and on the MessageBoard itself by "SourceMessageInterpreter{}")
 */
 
public class MessageReceptor  extends DataConnectorAbs{

        // =================================

        // object references ..............
        ReceptorDigestIntf taskPerformer;
        
        XRegistration xRegistration;

        XMessage xmsg ;
        
        StringedObjects stringedObj = new StringedObjects();
        
        // main variables / properties ....
        
        long regID;
        //MessageBoard msgboard;

        int listenPort = 0;
        String nameOfInstance = "";
        
        String originatorID;
        String roleOfSender;
        
        // helper objects .................

        DFutils fileutil = new DFutils();
        StringsUtil strgutil = new StringsUtil();

        PrintLog out = new PrintLog(2, true);
                
        // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
        public MessageReceptor(MessageBoardFactory mbf, XRegistration xreg) {
                super(mbf, xreg);

                if (xreg==null){
                        return;
                }
                xRegistration = xreg;
                regID = xRegistration.getInstanceID();

                this.mbf = mbf;
                mbf.setMessageReceptorReference(this);
                // msgboard is NULL for standalone participants !!
                this.msgboard = mbf.getMessageBoard();

                listenPort = xRegistration.getClientListeningPort();
                                                                                                                out.print(3, "\nstarting MessageReceptor (regID-" + regID+") on port " + listenPort + "...  ");

                // receiver = new UdpDataReceiver(listenPort, mbf.getServicePort(), this, "regID-" + regID);
                receiver = comBox.createReceiver(listenPort, mbf.getServicePort(), this,  "regID-"+regID );
                // comBox.getSender().release();
                // sender = comBox.createSender( mbf.getMessageBoard().getMsgPortforReceptors(),  mbf.getServicePort(), "regID-"+regID) ;
                xmsg = new XMessage(out);
        }
        // . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
        
        
        public void update(Observable observedObj, Object objdata) {
                
                // this describes the role of the instance we are now in
                String roleOfInstance = "",nameOfParticipant="";
                int p1,p2,r ;
                String repliedStr = "";
                XRegistration xreg = null ;
                
                
                repliedStr = (String) (objdata);
                
                if (repliedStr==null){
                                                                out.print(4, "\nMessageReceptor: reply string was empty (maybe, intentionally).");
                        return;
                }
                // participants should have registered only 1 item: themselves
                // since participants have their own MessageBoardFactory, (and their own ComBox as well)
                // we access the registration of the object
                if (this.mbf.registeredInstances.size()>0){
                        
                        xreg = this.mbf.registeredInstances.get(0);
                        roleOfInstance = xreg.getRole() ;
                        nameOfParticipant = xreg.getNameOfApplicant();
                }
                
                if (roleOfInstance.toLowerCase().contains("recept")){
                                        out.print(6, "\nmessage retrieved by MessageReceptor...  (role: "+roleOfInstance+", state: "+xRegistration.getConnectionState()+",name: "+nameOfParticipant+") ");
                }
                if ((repliedStr!=null) && (repliedStr.contains("confirmation"))){
                        p1=0;
                }           
if ( (( repliedStr.contains("<confirmation secret")) &&(repliedStr.contains("-1")==false)) ||
         ((repliedStr!=null) &&(repliedStr.contains("noresource xx") )) 
         ){// && (repliedStr.contains("<confirmation"))){
         
        out.print(6, "\n-----------------------------------------------------\n"+
                                 "update() in MessageReceptor: received message ...\n"+ repliedStr);
} // purely for DEBUG!! ... to get a grip on a particular message ...

if ((repliedStr!=null) &&(repliedStr.contains("bye") )) {// && (repliedStr.contains("<confirmation"))){
        out.print(5, "registration message received...");
        out.print(5, repliedStr + "\r\n=========================================");
} 
        
                // this is handling <transaction> and <response> messages
                if (primaryDispatchOfReceivedMessages(repliedStr)){ return ; };
                
                // this is handling <register> messages during lifecycle AFTER startup
                if (secondaryDispatchOfReceivedMessages(repliedStr)){ return ; };
                
                if ((repliedStr!=null) && (repliedStr.contains("<system"))  ){

                        r = handlingSystemMessages( repliedStr ) ;
                        
                        if (r==0){
                                return;
                        }
                        
                        
                        if ((repliedStr.contains("shutdown")) && (xreg!=null)){
                                digestingShutDownMessage(repliedStr,xreg);
                                return;
                        }

                        if ( (repliedStr.contains("<register>")) && (repliedStr.contains("<check")) && (repliedStr.contains("\"ping\""))){
                                taskPerformer.performSystemTask( "ping::" + repliedStr) ;
                                return;
                        }
                }
        
                boolean hb = xmsg.isXML(repliedStr);
                if (hb==false){
                        taskPerformer.handlingNonXmlContent( repliedStr );
                        return ;
                }
                out.print(3, "\n\n=============\nunhandled message in MessageReceptor:\n"+repliedStr+"\n=============\n");
        }

        
        private int  dispatcherStartup( String rawXmlStr ){
                int p1  ;
                int  result= 1 ;
                
                boolean hb;
                
                
                // if (receptorVariant_abc( xmsg, rawXmlStr ,rawIndicators) ){ return; }
                
                
                originatorID = xmsg.getInfoFromProlog( rawXmlStr, "origin", "id", ".");
                rawXmlStr = xmsg.removePrologFromXml(rawXmlStr) ;
                
                if (originatorID.length()==0){
                        originatorID = xmsg.getSpecifiedInfo(rawXmlStr, "//originator", "id") ;
                }
                if (originatorID.length()==0){
                        originatorID = xmsg.getSpecifiedInfo(rawXmlStr, "//origin", "id") ;
                }
                
                if (xmsg.isXML(rawXmlStr)== false){
                        
                        // also not completely correct for general purpose, 
                        // there should be a method digesting non-xml stuff ...
                        taskPerformer.performSystemTask(rawXmlStr) ;
                        
                        return -1;
                }
                
                roleOfSender = xmsg.getSpecifiedInfo(rawXmlStr,"//messageboard","role").toLowerCase() ;
                if ( roleOfSender==null) {
                        return -3;
                }
                
                hb = (roleOfSender.toLowerCase().contains("receptor")) ;
                if (hb == false){
                        // we accept also messages originated from board
                        hb = (roleOfSender.toLowerCase().contentEquals("board")) ;
                        
                        // factoryProperties.protocolId 
                        //if ((hb==false) && (mbf.getFactoryProperties().protocolId >= MessageBoardFactoryProperties.protocolTCP))
                        if (hb==false){
                            hb = (( rawXmlStr.contains("<transaction>")) && (roleOfSender.toLowerCase().contains("source"))) ;
                                //hb = (roleOfSender.toLowerCase().contains( mbf.participantsRole.toLowerCase())) ; // "source")) ;
                                
                        }
                }
                
                if (hb == false){
                        // ...but directly from source only if such direct connections are allowed 
                        // the MessageBoard acts as a name-server then!
                        if (mbf.getDirectConnectionsAmongParticipants()){
                                // hb = (roleOfSender.toLowerCase().contains("source")) ;
                                hb = (roleOfSender.toLowerCase().contains( mbf.participantsRole.toLowerCase())) ;
                        }
                }
                                
                if (hb){
                        result=0;
                }
                
                return result ;
        }
        
        

        /**
                 * 
                 * this should be a class according to an interface, such that one could overwrite the filter  
                 * @param rawXmlStr
                 * @return
                 */
                private boolean primaryDispatchOfReceivedMessages(String rawXmlStr){
                        
                        int p1,r;
                        boolean result ;
                        String[] rawIndicators;
                        
                         
                        
                        r = dispatcherStartup( rawXmlStr );
                        if (r<0){
                                return false ;
                        }
                        if (r>0){
                                r=r+0;
                        }
                        
                        p1 = rawXmlStr.indexOf("<transaction>");
                        
                        if ((p1>0) && (r==0)){
                                
        if (rawXmlStr.contains("cancelxyz")){
                out.print(5, "\n\rcancel request, raw ...\n\r"+rawXmlStr) ;
        }
                                rawIndicators = new String[]{"role=\"SOURCE","<transactionID","<request task="} ;
                                result = rawIndicatorsCheck( rawXmlStr, rawIndicators);
        
                                if ( (taskPerformer!=null) &&( result )){
                                 // ReceptorDigestIntf , in MessageBoardParticipant, class MessageReceptorDigester
                                
                                        // data from source flowing in...
                                        
                                        if (xRegistration.getConnectionState() <= CNX_AVAIL ){
                                        
                                                xRegistration.setConnectionState( CNX_BUSY ) ;  
                                                out.print(5, "state set to CNX_BUSY ("+CNX_BUSY+") for connection "+ xRegistration.getDataConnector().toString());
                                                
                                                confirmTransactionAcceptance( rawXmlStr );
                                                // this parses the xml and creates a task package from it
                                                handlingRoutedTransactions( rawXmlStr );
                                         
                                                return true;
                                        } else{
                                                out.print(2, "task message not accepted by RECEPTOR (id:"+xRegistration.getInstanceID()+"), "+
                                                                         "reason : state="+xRegistration.getConnectionState()+"  for connection "+ xRegistration.getDataConnector().toString());
                                                // receptor is busy, thus we return a state message
                                                reflectRoutedTransaction( rawXmlStr, CNX_BUSY );
                                                return true;
                                        }
                                }
                                // ----------------------------------
        
                                rawIndicators = new String[]{"<transaction>","<confirmation", "type=\"delivery" } ;
                            if (handling_ConfirmationAboutResultDelivery( xMessage, rawXmlStr , rawIndicators)){
                                return true;
                            }
        
                            
                                rawIndicators = new String[]{"<control ", "<task ", "type=\"cancel\"" } ;// "<transaction>", , already checked for...
                                if (handling_CancelSelectedTask( xMessage, rawXmlStr , rawIndicators)){
                                        return true;
                                }
                                
                                
                        } // "<transaction>" contained in xml?
        
                        p1 = rawXmlStr.indexOf("<response>");
        
                        if (p1>0){
                                
                                
                                rawIndicators = new String[]{"<return ", "content=\"resource", "type=\"task\"","<resource value=" } ; // <transaction>", already checked for...
                            if (handling_ReceivedResourceKeyForTaskDownload( xMessage, rawXmlStr , rawIndicators)){
                                return true;
                            }
                        }
                         
                        rawIndicators = new String[]{"<register","<notification ", "type=\"connection\"" } ;
                    if (handling_NotificationAboutConfirmedConnection( xMessage, rawXmlStr , rawIndicators)){
                        return true;
                    }           
                        
        
                        
        
                        // checking whether we get sth for the SOURCE which embeds a receptor 
                        // yet, should not then the callback point to somewhere else ???
                        
                        rawIndicators = new String[]{"<transaction>","\"SOURCE" } ;
                        if (rawIndicatorsCheck( rawXmlStr, rawIndicators)){ return true;};
        
                        
                        result=false;
                        
                        if (result) {
                                // <transactionID value="  <data
                        }
                        return result ;
                }
        private boolean secondaryDispatchOfReceivedMessages(String rawXmlStr){
                int p1,r;
                boolean result=false ;
                String[] rawIndicators;
                
                 
                
                
                r = dispatcherStartup( rawXmlStr );
                if (r<0){
                        return false ;
                }
                
                
                p1 = rawXmlStr.indexOf("<register>");
                
                if ((p1>0) && (r==0)){
                        
                                                                                                out.print(2, "secondary dispatching, e.g. renewal of registration : \n"+rawXmlStr) ;
                        
                        rawIndicators = new String[]{"<state ","<notification ", "type=\"registration", "valid=" } ; 
                    if (handling_adviceForReRegistration( xMessage, rawXmlStr , rawIndicators)){
                        return true;
                    }
                        
                }
                
                return result;
        }
        
        
        private int handlingSystemMessages( String rawXmlStr ) {
                int result=-1 ;
                
                ParticipantsSysMsgInterpreter participantsSysMsgInterpreter;
                
                try{
                
                        
                        
                        participantsSysMsgInterpreter = new ParticipantsSysMsgInterpreter( mbf,  xRegistration, 
                                                                                                                                                           taskPerformer,  
                                                                                                                                                   nameOfInstance, out ) ;
 
                        result = participantsSysMsgInterpreter.interpretingSysMessage( rawXmlStr ) ;
                         
                        
                }catch(Exception e){
                        if (result >=0){
                                result = -3;
                        }
                        out.printErr(2, "Exception in handlingSystemMessages(): "+e.getMessage() );
                        e.printStackTrace() ;
                }
                
                return result;
        }

        
        
        
        private void handlingRoutedTransactions( String rawXmlStr ){
                        /*
                        <?xml version="1.0" encoding="UTF-8"?>
                        <messageboard name="spela" role="SOURCE">
                                <transaction>
                                        <transactionID value="45"/>
                                        <content type="rawdata"/>
                                        <data type="9">
                                        <format encoding="base64" zip="0"/>
                                        <values>
                                                        That's a real data table!
                                        </values>
        
                                        </data>
                                        <request task=""/>
                                </transaction>
                        </messageboard>
                        
                        */
                                                                                                                out.print(5,"routed transaction... \n"+rawXmlStr);
                        
                        
                int p1, p2,p3 ;
                long transactionID = -1, instanceID;
                String xmlstr,str,  xTaskStr;
        
                TaskPackage taskPackage;
                                
        
                
                p1 = rawXmlStr.indexOf("<transaction>");
                p2 = rawXmlStr.indexOf("<transactionID ");
                p3 = rawXmlStr.indexOf("<request task=\"");
                if ((p1 > 0) && (p2 > 0) && (p3>0)) {
        
                        p1 = rawXmlStr.indexOf("<data ");
                        // is it really a data task ...
                        p1 = 3;
                        
                        
                        mirrTransaction = xMessage.readReceptorTransaction(rawXmlStr);
                        mirrTransaction.setState(Transaction.TS_DATA_ACCEPTING);
                        
                        transactionID = mirrTransaction.getTransactionID();
                                                                                                out.print(3, "\nhandlingRoutedTransactions(), Message Receptor accepted transaction <" + transactionID+ "> to relay ...");
                        
                        // get task data str, which is actually a serialized object
                        xTaskStr = mirrTransaction.getDataObject() ;
                        
                        // re-creating the task package: it contains everything the RECEPTOR needs to know about 
                        taskPackage = (TaskPackage)stringedObj.decode(xTaskStr) ;
                        
                        // additional info for the RECEPTOR
                        taskPackage.setTransactionID( transactionID ) ;
                        taskPackage.setTransactionMirror( mirrTransaction );
                        // send the notification about being busy here, about getting this task 
                        
                        instanceID = mirrTransaction.getInstanceID() ;
                        
                        xRegistration.sendStateToMsgBoard( instanceID, transactionID, xRegistration.getRole(),Transaction.TS_TASK_ACCEPTED, "") ;
                        mirrTransaction.setState(Transaction.TS_TASK_ACCEPTED);
                        
                        // performing the callback to the performer on the side of the RECEPTOR
                        taskPerformer.performTask( taskPackage ) ; 
                        // we have to send a confirmation there
                         
                          
                        
                } //
        
                
        } // handlingRoutedTransactions

        
        private boolean handling_ReceivedResourceKeyForTaskDownload( XMessage xMessage, String rawXmlStr , String[]rawIndicators){
                /*
                        <response>
                        <return content="resource" type="task"/>
                        <instanceID value="2550"/>
                        <resource value="cd1bb820-9a43-42bb-ab8f-4c9c4083a50b"/>
                        </response>
                 */
                boolean result=false; 
                int ix,sv,r;
                long tid, iid;
                String resourceKeyStr, xmloutmsg, xmlRestPrefix,role ;
                Transaction transaction;
                ParticipantsDeliveryPadIntf dpad ;
                
                
                result = rawIndicatorsCheck( rawXmlStr, rawIndicators);
                
                if (result){
                                                                                                out.print(4, "... while checking for TASKS, response received by MessageReceptor ...");
                        
                        tid = xMessage.getSpecifiedValue(rawXmlStr, "//response/transactionID","value") ;
                        iid = xMessage.getSpecifiedValue(rawXmlStr, "//response/instanceID","value") ;
                        // is the iid correct ?
                        resourceKeyStr = xMessage.getSpecifiedInfo(rawXmlStr, "//response/resource", "value") ; 
                        
                        /*
                         * additionally to the transaction id we get the resource key, which lives in a Map on the side
                         * of the MessageBoard;
                         * in httpc, we do not have a transactionID when contacting the MessageBoard for a task
                         * the next call will initiate the download via get... 
                         * the MessageBoard will return the complete xml which also is embedding the taskpackage
                         * this, then, we will digest as normal    
                         */
                 
                        //acceptedTransactionIDs

                                                                                                
                        if ((tid<0) || (resourceKeyStr.contentEquals("noresource"))){
                                transaction=null;
                                if (tid>=0){
                                        // inform the deliverypad, and the notification mechanism
                                        ix = mbf.getTransactions().getIndexByTransactionID(tid, 1);
                                        transaction = mbf.getTransactions().getItem(ix) ;
                                }
                                
                                if (transaction != null){
                                                                                                out.printErr(2, "digesting confirmation: updating state, informing DeliveryPad...");
                                        sv = transaction.getTransactState() ; 
                                        if ((sv>0) && (sv < Transaction.TS_RESULTS_BUFFERED )){
                                                transaction.setTransactState(Transaction.TS_RESULTS_BUFFERED);
                                        }
                                
                                        if (xRegistration!=null){
                                                role = mbf.getFactoryProperties().getParticipantsRole() ;
                                                dpad = mbf.getDeliveryPad( role, xRegistration.getSuffixUID()) ; // second instance 
                                                if (dpad!=null){
                                                        dpad.digestingConfirmation(tid) ;
                                                }
                                        }
                                }
                                return true;
                        }
                                                                                                out.print(3, "preparing download of task resource for key : "+resourceKeyStr);
                        xmloutmsg = xMessage.createDownloadRequestForTaskResource( tid, iid, resourceKeyStr, "RECEPTOR" ) ;
                        

                        // insert pre-amble...

                        mbf.comBoxFactory.setObserver(this)  ; 
                        // it is not a "get" which would work just through the (virtual) address
                        xmlRestPrefix = xMessage.createRestletRoutingPrefix("", "/data", "post");
                        
                        xmloutmsg =  xmlRestPrefix + xmloutmsg; // a prolog which will be removed by restlet framework connector
                        
                        // not doing this: xRegistration.sendRequestPackage( rawXmlMsg )  ;
                        // it uses dataconnector, which then is also the observer
                                                                                                out.print(3,"\n----------------\nRECEPTOR: prepared request for downloading the task ... \n----------------\n\r"+xmloutmsg);
                        
                        SenderWrap sender = new SenderWrap( mbf.getComBoxFactory().getComBox() );
                        r = sender.sendingMessage(xmloutmsg , 0);
                                if (r<0){
                                        out.printErr(3, "sendingMessage() failed in handling_ReceivedResourceKeyForTaskDownload(), code="+r);
                                }
                        sender = null;
                         
                }
                return result;
        }
        
        private boolean handling_CancelSelectedTask( XMessage xMessage, String rawXmlStr , String[]rawIndicators){
                /*
                        <messageboard name="spela" role="SOURCE">
                                <transaction>
                                <control secret="53c34c91-cb88-419d-81b7-d91b7f723bc8"/>
                                <transaction id="446"/>
                                <instance id="1867"/>
                                <task param="" type="cancel"/>
                        </transaction>
                        </messageboard> 
                 */
                boolean hb=false, result = false;
                
                long iid, tid;
                String str;
                TaskPackage taskPackage = new TaskPackage(); 
                
                
                result = rawIndicatorsCheck( rawXmlStr, rawIndicators);
                
                if (result){
                                                                                                out.print(3, "CANCEL request received...    ");
                                                                                                
                        tid = xMessage.getTransactionID(rawXmlStr) ;
                        iid = xMessage.getSpecifiedValue(rawXmlStr, "instance","id"); // getinstanceID(rawXmlStr, "instance") ;
                        
                        str = xMessage.getSpecifiedInfo(rawXmlStr, "task", "type");
                        
                        if ((str.contentEquals("cancel")) && (tid>0) && (iid>0)){
                                                                                                out.print(3, "CANCEL request data decoded: tid="+tid+", iid="+iid+"...    ");
                            
                                taskPackage.setTypeOfProceedings("task");
                                taskPackage.setTransactionID(tid) ;
                                taskPackage.setDataString("cancel");
                                
                                taskPerformer.performTask( taskPackage ) ; 
                                // "cancel::" + tid+"="+tid) ;
                                
                            // getRegisteredInstances()
                        } // criteria fulfilled
                        
                }
                
                return result ;
        }
        
        /**
         * 
         * this should stop attempts to send the message, hence we will also inform the deliverypad through the taskPerformer
         * 
         * @param xMessage
         * @param rawXmlStr
         * @param rawIndicators
         * @return
         */
        private boolean handling_ConfirmationAboutResultDelivery( XMessage xMessage, String rawXmlStr , String[]rawIndicators){
                /*
                  
                  <messageboard name="spela" role="BOARD">
                        <transaction>
                        <transaction id="349"/>
                        <confirmation secret="" type="delivery"/>
                        <instance id="2416"/>
                        </transaction>
                </messageboard>

                 */
                
                boolean  result = false;
                long transactionID;
                String roleOfSender ;
                int stateFlag;
                
                TaskPackage taskPackage = new TaskPackage();
                
                
                result = rawIndicatorsCheck( rawXmlStr, rawIndicators);
                
                if (result){
                                                                                out.print(3, "handling_ConfirmationAboutResultDelivery()...");
                                                                                out.print(4, ""+rawXmlStr);
                                                                                
                        roleOfSender = xMessage.getSpecifiedInfo(rawXmlStr, "messageboard", "role") ;
                        // should be "BOARD"
                        stateFlag = (int) xMessage.getSpecifiedValue(rawXmlStr, "confirmation", "state") ;
                        
                        transactionID = xMessage.getTransactionID(rawXmlStr);
                        
                        taskPackage.setDataString("delivery") ;
                        taskPackage.setTypeOfProceedings("confirmation") ;
                        
                        int sv=1;
                        if (stateFlag>0){
                                sv=stateFlag;
                        }
                        taskPackage.setStateFlag(sv); 
                        
                        taskPackage.setTransactionID(transactionID) ;
                        
                        // executing the callback in:  MessageBoardParticipant::handling_deliveryConfirmation()
                        taskPerformer.performTask(taskPackage) ;
                        
                }
                        
                return result ;
        }

        private boolean handling_NotificationAboutConfirmedConnection( XMessage xMessage, String rawXmlStr , String[]rawIndicators){
                /*
                 <messageboard name="spela" role="BOARD">
                        <transaction>
                        <register>
                                <notification type="connection" value="1"/>
                                <name value="testsource0-source-1-7132c490-f138-11e0-84ce-e0f847024516"/>
                        </register>
                        </transaction>
                 </messageboard>
                  
                 */
                boolean hb=false, result = false;
                
                
                                                                                                 
                result = rawIndicatorsCheck( rawXmlStr, rawIndicators);
                
                if (result){
                        
                        hb = xMessage.checkConnectionConfirmationMatch ( rawXmlStr, xRegistration.getInstanceID(), xRegistration.getNameOfApplicant());
                 
                        if (hb){
                                // set xreg0s connection finally to active, 
                                // server-side, this is important for the client-matcher
                                xRegistration.setInstanceConnectionConfirmed(true);
                                out.print(3, "Instance is now connected to MessageBoard, and connection has been confirmed.");
                                
                                taskPerformer.performSystemTask("startup::complete");
                        }else{
                                // this condition may occur in case of request for unique registration that can not be satisfied
                                hb = xMessage.checkConnectionConfirmationMatch ( rawXmlStr, -1, xRegistration.getNameOfApplicant());
                                if (hb){
                                        xRegistration.setInstanceConnectionConfirmed(true);
                                        out.print(3, "Instance is now connected to MessageBoard, yet using an ID that is different from the desired one, and connection has been confirmed.");
                                }else{
                                        out.print(2, "Instance (type:receptor) tried to connect to MessageBoard, but connection has not been confirmed.");
                                        out.print(4, rawXmlStr);
                                        // ...so we check it again ?? -> "MessageBoardParticipant::MessageReceptorDigester{}"
                                        taskPerformer.performSystemTask("startup::getconfirm"); // so far nothing happens there
                                }
                        }
                }
                System.gc();  
                return result ;
        }
        
        private boolean handling_adviceForReRegistration(  XMessage xMessage, String rawXmlStr , String[]rawIndicators){
                
                /*
                        <messageboard name="spela" role="BOARD">
                                <register>
                                        <instance id="2757"/>
                                <notification type="registration"/>
                                <state description="description" valid="-1" value="-1"/>
                                </register>
                                <originator id="BaseResource$MessageSupply@e0a386" />
                        </messageboard>
                 */
                boolean hb=false, result = false;
                String str;
                int validityCode, statevalue;
                long instanceID;
                
                
                 
                result = rawIndicatorsCheck( rawXmlStr, rawIndicators);
                
                if (result){
                        
                        instanceID = xMessage.getSpecifiedValue(rawXmlStr, "instance","id"); //getinstanceID(rawXmlStr, "instance") ;
                        str = xMessage.getSpecifiedInfo(rawXmlStr, "//notification", "type") ; 
                        if (str.contentEquals("registration")==false){
                                return false;
                        }
                        
                        validityCode = (int)xMessage.getSpecifiedValue(rawXmlStr, "//state", "valid") ;
                        statevalue =  (int)xMessage.getSpecifiedValue(rawXmlStr, "//state", "value") ;
                                
                        if (validityCode<0){
                                // re-register !
                                
                                                                        out.printErr(2, "instance (id="+instanceID+") received the advice to re-register after loss of connection (code:"+statevalue+").");
                                
                                taskPerformer.performSystemTask("restart::instanceID="+instanceID) ;
                        } // <0
                        
                }
                
                return result ;
        }
        
        
        
        private void reflectRoutedTransaction( String rawXmlStr, int cnxStateForMB ){
 
                 
                taskPerformer.performSystemTask("state::"+Transaction.TS_TASK_DENIED+"::"+rawXmlStr ) ;                                           
        }
        
        private void confirmTransactionAcceptance( String rawXmlStr ){
                
                
                taskPerformer.performSystemTask("state::"+Transaction.TS_TASK_DELIVERED+"::"+rawXmlStr ) ; 
                // it should return.... is the delivery pad available on the way ... ...or NO_WAIT for sender
        }
        
        
        
        
        
        private void digestingShutDownMessage( String repliedStr, XRegistration xreg ){
        /*
                <messageboard name="spela" role="BOARD">
                        <system>
                                <shutdown id="1794" name="testReceptor-receptor-1-dd8b92d4-b6fb-4e41-b1d6-88d38ead6762" role="RECEPTOR"/>
                        </system>
                </messageboard>
         */
                String str;
                long iid = -1;
                
                str = xmsg.getSpecifiedInfo(repliedStr, "//shutdown", "id");
                          if (str.length()>0){
                                  iid = Long.parseLong(str) ;
                          }
                str = xmsg.getSpecifiedInfo(repliedStr, "//shutdown", "name");
                if ( ( str.contentEquals( xreg.getNameOfApplicant() )) || (iid==xreg.getInstanceID())){
                        out.printErr(2, "\nRECEPTOR instance received a shutdown message broadcasted by the MessageBoard");
                        out.printErr(2, "This instance will shutdown, too.");
                        // closing all threads... processes... saving open stuff
                         
                        taskPerformer.performSystemTask("shutdown");
                        // this will initiate the proper disconnect procedure... 
                }
        
        }

        private boolean rawIndicatorsCheck( String rawXmlMsg, String[] rawIndicators){
                boolean rB=false;
                int isum=0;
                
                int[] p = new int[rawIndicators.length] ;
                
                for (int i=0;i<rawIndicators.length;i++){
                        p[i] = rawXmlMsg.indexOf( rawIndicators[i]);
                        
                        if (p[i]>=0){
                                isum = isum+ 1;
                        }
                }
                
                rB = (isum == p.length) ;
                
                return rB;
        }

        
        public void setNameOfInstance(String nameOfInstance) {
                this.nameOfInstance = nameOfInstance;
        }

        public  void setTaskPerformer(ReceptorDigestIntf taskperformer) {
                taskPerformer = taskperformer;
        }

        
        // this is a jump-back address for catching expired data transfers, and
        // to resend them
        public void resend(String completeXmlMsg) {
         
                
        }
 
}
